import re
import sys
import os

from http import HTTPStatus

from GeneralRequestHandler import GeneralRequestHandler
from SessionManager import SessionManager

thisDir = os.path.split(os.path.realpath(__file__))[0]
sys.path.append(os.path.join(thisDir, "..", "common"))
sys.path.append(thisDir)

import EJOConst
import EJOConfig
from EJOServerInitializer import EJOServerInitializer

import logging
logger = logging.getLogger(__name__)

class EJOServerRequestHandler(GeneralRequestHandler):
    def __init__(self, request, client_address, server):
        # If there is any init job important to each member function
        # It should be done before supper().__init__
        # Because the root parent BaseRequestHandler will call member function in its __init__
        logger.debug("[EJOServerRequestHandler.EJOServerRequestHandler]")
        super().__init__(request, client_address, server)

    def _parseRequest(self):
        logger.debug(f"[EJOServerRequestHandler.parseRequest] {self.requestline}")
        reRequest = re.compile("GET +/(.*) +HTTP.*")
        matchRequest = reRequest.match(self.requestline)
        if matchRequest is None:
            self._handleError(HTTPStatus.BAD_REQUEST, "No valid GET request")
            return None, None
        if len(matchRequest.group(1)) < 1:
            logger.debug("Empty request, take as web login")
            return "page", [("id", EJOConst.PageLogin), ("client", EJOConst.ClientHtml), (EJOConst.Session, "")]
        reAPI = re.compile(f"({EJOConfig.API_CMD_REG})(\\?)?(.+)?")
        matchAPI = reAPI.match(matchRequest.group(1).strip())
        if matchAPI is None:
            self._handleError(HTTPStatus.BAD_REQUEST, "Bad API")
            return None, None
        cmd = matchAPI.group(1)
        params = []
        if matchAPI.group(2) is None or matchAPI.group(3) is None:
            return cmd, params
        reParam = re.compile(f"({EJOConfig.API_PARAM_NAME_REG})=({EJOConfig.API_PARAM_VALUE_REG})")
        for param in matchAPI.group(3).split("&"):
            matchParam = reParam.match(param)
            if matchParam is None:
                self._handleError(HTTPStatus.BAD_REQUEST, "Bad param")
                return None, None
            params.append((matchParam.group(1), matchParam.group(2)))
        return cmd, params

    # Do not use self.* in this function because it will run in new working thread
    def _handleRequst(self, cmd, params):
        api = SessionManager().GetProperty(EJOConst.SESSION_PROPERTY_API)
        if not api.ValidateAPI(cmd, params):
            return False, HTTPStatus.BAD_REQUEST, None, f"Invalid cmd and params: {cmd}, {params}"
        handlerName = api.GetHandler(cmd)
        handlers = SessionManager().GetProperty(EJOConst.SESSION_PROPERTY_API_HANDLER)
        if not handlerName or handlerName not in handlers:
            return False, HTTPStatus.NOT_IMPLEMENTED, None, f"No handler defined for cmd and params: {cmd}, {params}"
        handled, status, result = handlers[handlerName]().Handle(cmd, params)
        encodeResult = result.encode("utf-8", "surrogateescape") if handled else result
        return handled, status, str(len(encodeResult)), encodeResult

